﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO.Ports;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Windows.Threading;

namespace ComTools
{
    public partial class Form2 : Form
    {
        public Form2()
        {
            InitializeComponent();
        }

        private void InitComports()
        {
            cmbxComports.Items.Clear();
            cmbxComports.Items.AddRange(System.IO.Ports.SerialPort.GetPortNames());
            if (cmbxComports.Items.Count > 0)
            {
                cmbxComports.SelectedIndex = 0;
                btnOpenCom.Enabled = true;
            }
            else
            {
                btnOpenCom.Enabled = false;
            }
            //
            cmbBaudRate.SelectedIndex = 0;
            //
            string[] bitsSource = Enum.GetNames(typeof(System.IO.Ports.StopBits));
            cmbStopBits.DataSource = bitsSource;
            cmbStopBits.SelectedIndex = Array.IndexOf(bitsSource, System.IO.Ports.StopBits.One.ToString());
            string[] paritySource = Enum.GetNames(typeof(System.IO.Ports.Parity));
            cmbParity.DataSource = paritySource;
            cmbParity.SelectedIndex = Array.IndexOf(paritySource, System.IO.Ports.Parity.None.ToString());
        }

        private byte[] getCommBytes(string comm)
        {
            string xx = comm.Trim().Replace(" ", "").Replace("-", "").Replace(",", "");
            //不是偶数位，
            if (xx.Length % 2 != 0)
            {
                xx = xx + "0";
            }
            List<Byte> lists = new List<byte>();
            for (int x = 0; x < xx.Length; x = x + 2)
            {
                Byte b = Convert.ToByte(xx.Substring(x, 2), 16);
                lists.Add(b);
            }
            return lists.ToArray();
        }

        Random random = new Random(new Random().Next(0, 999));

        private List<string> getCommandStr(DataTable dataTable)
        {
            List<string> lists = new List<string>();
            //
            DataTable converters = dataTable.DefaultView.ToTable(true, "converter_addr");
            foreach (DataRow drConv in converters.Rows)
            {
                string addr = drConv["converter_addr"].ToString();
                //
                string sb = getCommandStr(dataTable, addr);
                //
                lists.Add(sb);
            }
            //
            return lists;
        }

        private string getCommandStr(DataTable dataTable, string addr)
        {
            StringBuilder sb = new StringBuilder();
            //sb.Clear();

            sb.Append(addr).Append(" ");
            sb.Append("80").Append(" ");
            sb.Append("10").Append(" ");
            //
            DataTable converters = dataTable.DefaultView.ToTable(true, "converter_addr");
            DataRow row = converters.Select("converter_addr = '" + addr + "'").FirstOrDefault();
            if (row != null)
            {
                for (int i = 0; i < 8; i++)
                {
                    int value = 0;
                    DataRow[] rows = dataTable.Select("converter_addr = '" + addr + "' and bit_sn = " + (i + 1).ToString());
                    if (rows.Length > 0)
                    {
                        int fromValue = Convert.ToInt32(rows[0]["value_from"]);
                        int toValue = Convert.ToInt32(rows[0]["value_to"]);
                        value = random.Next(fromValue, toValue);
                    }
                    sb.Append(value.ToString("X4")).Append(" ");
                }
                //
            }
            else
            {
                for (int i = 0; i < 8; i++)
                {
                    sb.Append(random.Next(4000, 20000).ToString("X4")).Append(" ");
                }
            }
            //
            byte[] aa = getCommBytes(sb.ToString());
            sb.Append(CRC.ToCRC16(aa));
            //
            return sb.ToString();
        }

        private void OpenRun()
        {
            if (timerCallback == null)
            {
                timerCallback = new System.Threading.TimerCallback((state) =>
                {
                    if (!SerialPortIsOpen())
                    {
                        return;
                    }
                    //string comm = "01 80 10 00 02 00 02 00 02 00 02 00 02 00 02 00 02 00 02 D0 6F ";
                    DataTable dt = GetDataTable();
                    List<string> lists = getCommandStr(dt);
                    for (int i = 0; i < lists.Count; i++)
                    {
                        string str = lists[i];
                        Output(str);
                        byte[] bytes = getCommBytes(str);
                        if (i > 0)
                        {
                            System.Threading.Thread.Sleep(50);
                        }
                        if (SerialPortIsOpen())
                        {
                            serialPort1.Write(bytes, 0, bytes.Length);
                        }
                    }

                });
            }
            object instate = null;
            decimal d = nudInterval.Value;
            timer = new System.Threading.Timer(timerCallback, instate, 1000, Convert.ToInt32(d) * 1000);
        }

        private void BtnLoadComports_Click(object sender, EventArgs e)
        {

        }

        private void BtnOpenCom_Click(object sender, EventArgs e)
        {
            if (cmbxComports.SelectedIndex < 0)
            {
                return;
            }
            string compName = cmbxComports.SelectedItem.ToString();
            serialPort1.PortName = compName;
            //
            serialPort1.BaudRate = int.Parse(cmbBaudRate.SelectedItem.ToString());
            serialPort1.DataBits = int.Parse(txtDataBits.Text.Trim());
            serialPort1.StopBits = (System.IO.Ports.StopBits)Enum.Parse(typeof(System.IO.Ports.StopBits), cmbStopBits.SelectedItem.ToString());
            serialPort1.Parity = (System.IO.Ports.Parity)Enum.Parse(typeof(System.IO.Ports.Parity), cmbParity.SelectedItem.ToString());
            serialPort1.ReceivedBytesThreshold = (int)nudBytesThreshold.Value;
            //
            try
            {
                serialPort1.Open();
                //
            }
            catch (Exception exc)
            {
                MessageBox.Show(exc.Message);
            }
        }

        System.Threading.Timer timer = null;
        System.Threading.TimerCallback timerCallback = null;
        private delegate bool DelBooleanValue();
        private delegate DataTable DelDataTable();
        private delegate void Outptu(string msg);

        private DelBooleanValue delBooleanValue = null;

        private bool SerialPortIsOpen()
        {
            if (delBooleanValue == null)
            {
                delBooleanValue = new DelBooleanValue(() =>
                {
                    return serialPort1.IsOpen;
                });
            }
            return delBooleanValue.Invoke();
        }

        private DelDataTable delDataTable = null;

        private DataTable GetDataTable()
        {
            if (delDataTable == null)
            {
                delDataTable = new DelDataTable(() =>
                {
                    return dataGridView1.DataSource as DataTable;
                });
            }
            return delDataTable.Invoke();
        }

        private DataTable initData()
        {
            DataTable dataTable = initTableSchema();
            //
            addRows(dataTable, 1);
            //
            return dataTable;
        }

        private DataTable initTableSchema()
        {
            DataTable dataTable = new DataTable();
            dataTable.Columns.Add("converter_addr", typeof(string));
            dataTable.Columns.Add("bit_sn", typeof(int));
            dataTable.Columns.Add("value_from", typeof(int));
            dataTable.Columns.Add("value_to", typeof(int));
            //
            return dataTable;
        }

        private void addRows(DataTable dataTable, int nums = 5)
        {
            for (int c = 1; c <= nums; c++)
            {
                for (int i = 1; i <= 8; i++)
                {
                    dataTable.Rows.Add(c.ToString("X2"), i, 4000, 20000);
                }
            }
        }

        private Outptu output = null;

        private void Output(string txt)
        {
            if (output == null)
            {
                output = new Outptu((otext) =>
                {
                    textBox1.AppendText(otext);
                    textBox1.AppendText(Environment.NewLine);
                });
            }
            textBox1.BeginInvoke(output, txt);
            //miOutput.BeginInvoke(null, null);
        }

        private void Form2_Load(object sender, EventArgs e)
        {
            InitComports();
            dataGridView1.DataSource = initData();
            BindCombobox();
            SP3State(false);
            initTabPage3();
        }

        private void BtnClose_Click(object sender, EventArgs e)
        {
            if (timer != null)
            {
                timer.Change(System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite);
            }

            serialPort1.Close();
        }

        private void BtnAutoSend_Click(object sender, EventArgs e)
        {
            //主动发送
            if (SerialPortIsOpen())
            {
                OpenRun();
            }
            //取消响应回复
            serialPort1.DataReceived -= SerialPort1_DataReceived;
        }

        private void BtnSendStop_Click(object sender, EventArgs e)
        {
            if (timer != null)
            {
                timer.Change(System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite);
            }
        }

        private void btnResponse_Click(object sender, EventArgs e)
        {
            //取消主动发送
            if (timer != null)
            {
                timer.Change(System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite);
            }
            serialPort1.DataReceived -= SerialPort1_DataReceived;
            serialPort1.DataReceived += SerialPort1_DataReceived;
        }

        Random randomResponse = new Random(999);

        private void SerialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        {
            SerialPort sp = sender as SerialPort;
            System.Threading.Thread.Sleep(50);
            byte[] tempBytes = new byte[sp.BytesToRead];
            int i = sp.Read(tempBytes, 0, tempBytes.Length);
            byte[] crcBytes = tempBytes.Skip(tempBytes.Length - 2).Take(2).ToArray();
            byte[] origBytes = tempBytes.Take(tempBytes.Length - 2).ToArray();
            string crc = CRC.ToModbusCRC16(origBytes);
            string crc2 = BitConverter.ToString(crcBytes).Replace("-", "");
            if (!crc.Equals(crc2))
            {
                return;
            }
            //
            byte addr = tempBytes[0];
            byte[] other = tempBytes.Skip(1).Take(tempBytes.Length - 1 - 2).ToArray();
            string otherS = BitConverter.ToString(other).Replace("-", "");
            if (otherS == "0400000020" || otherS == "0400400008")
            {
                byte[] backData = new byte[21];
                //
                byte[] result = new byte[19];
                result[0] = tempBytes[0];
                result[1] = tempBytes[1];
                result[2] = 16;
                //
                byte[] x = getTempValue(addr, 1);
                result[3] = x[0];
                result[4] = x[1];
                //
                x = getTempValue(addr, 2);
                result[5] = x[0];
                result[6] = x[1];
                //
                x = getTempValue(addr, 3);
                result[7] = x[0];
                result[8] = x[1];
                //
                x = getTempValue(addr, 4);
                result[9] = x[0];
                result[10] = x[1];
                //
                x = getTempValue(addr, 5);
                result[11] = x[0];
                result[12] = x[1];
                //
                x = getTempValue(addr, 6);
                result[13] = x[0];
                result[14] = x[1];
                //
                x = getTempValue(addr, 7);
                result[15] = x[0];
                result[16] = x[1];
                //
                x = getTempValue(addr, 8);
                result[17] = x[0];
                result[18] = x[1];
                //
                result.CopyTo(backData, 0);
                string ss = CRC.ToCRC16(result);
                x = CRC.StringToHexByte(ss);
                backData[19] = x[0];
                backData[20] = x[1];
                //
                sp.Write(backData, 0, backData.Length);
                Output(BitConverter.ToString(backData));
            }

        }

        private byte[] getTempValue()
        {
            int x = randomResponse.Next(4000, 20000);
            return BitConverter.GetBytes(x);
        }

        private byte[] getTempValue(byte addr, int bitsn)
        {
            DataTable dt = GetDataTable();
            DataRow row = dt.Select("converter_addr = '" + addr.ToString("X2") + "' and bit_sn = " + bitsn.ToString()).FirstOrDefault();
            int x = randomResponse.Next(4000, 20000);
            if (row != null)
            {
                int value_from = Convert.ToInt32(row["value_from"]);
                int value_to = Convert.ToInt32(row["value_to"]);
                x = Convert.ToInt32(randomResponse.Next(value_from, value_to));
            }
            return BitConverter.GetBytes(x);
        }

        private void BtnCreateConverter_Click(object sender, EventArgs e)
        {
            DataTable dataTable = initTableSchema();
            //
            int num = Convert.ToInt32(nudConvertNums.Value);
            //
            addRows(dataTable, num);
            //
            dataGridView1.DataSource = dataTable;
        }

        private void BtnSetCellValues_Click(object sender, EventArgs e)
        {
            foreach (DataGridViewTextBoxCell cell in dataGridView1.SelectedCells)
            {
                cell.Value = nudValue.Value;
            }
            dataGridView1.EndEdit();
        }

        Socket socketReceive = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

        private void BtnListen_Click(object sender, EventArgs e)
        {
            int port = Convert.ToInt32(nudPortNum.Value);
            IPEndPoint endPoint = new IPEndPoint(IPAddress.Any, port);
            socketReceive.Bind(endPoint);
            socketReceive.Listen(100);


            IAsyncResult asyncResult = socketReceive.BeginAccept(new AsyncCallback(OnAccept), socketReceive);
            OutputLineTab2("正在等待接收呼入的连接");
        }

        private void OnAccept(IAsyncResult asyncesult)
        {
            Socket socket2 = asyncesult.AsyncState as Socket;
            Socket temp = socket2.EndAccept(asyncesult);
            //
            OutputLineTab2("收到呼入的请求");
            //
            byte[] vs = new byte[temp.Available];
            int i = temp.Receive(vs, SocketFlags.None);
            //temp.Close();

            string result = BitConverter.ToString(vs);
            OutputLineTab2(result);

            //开始下一次接收请求
            socket2.BeginAccept(new AsyncCallback(OnAccept), socket2);
        }

        private void OutputTab2(string txt)
        {
            richTextBox1.BeginInvoke(new MethodInvoker(() =>
            {
                richTextBox1.AppendText(txt);
            }));
        }

        private void OutputLineTab2(string txt)
        {
            richTextBox1.BeginInvoke(new MethodInvoker(() =>
            {
                richTextBox1.AppendText(txt);
                richTextBox1.AppendText(Environment.NewLine);
            }));
        }

        private void BtnListenStop_Click(object sender, EventArgs e)
        {
            if (socketReceive != null)
            {
                try
                {
                    //socketReceive.Disconnect(false);
                    //socketReceive.Shutdown(SocketShutdown.Both);
                    socketReceive.Close();
                }
                catch (Exception exc)
                {
                    OutputLineTab2(exc.Message);
                }
            }
        }

        AsyncCallback connectCallBack = null;

        private void BtnConnect_Click(object sender, EventArgs e)
        {
            Socket socketSend = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            int port = Convert.ToInt32(nudPortNum.Value);

            if (connectCallBack == null)
            {
                connectCallBack = new AsyncCallback(DealConnectBack);
            }
            if (!socketSend.Connected)
            {
                IAsyncResult asyncResult = socketSend.BeginConnect(txtIPAddr.Text.Trim(), port, connectCallBack, socketSend);
                OutputLineTab2("正在连接中...");
            }
        }

        private void DealConnectBack(IAsyncResult async)
        {
            Socket connReceive = async.AsyncState as Socket;
            connReceive.EndConnect(async);
            //
            OutputLineTab2("连接成功，准备发送");
            string command = txtSend.Text.Trim().Replace("-", "").Replace(" ", "");
            //byte[] rr = Encoding.UTF8.GetBytes("010400000020F1D2");
            byte[] rr = CRC.StringToHexByte(command);
            int i = connReceive.Send(rr, SocketFlags.None);
            //
            OutputLineTab2("已发送成功");
            //
            byte[] resultByte = new byte[1024];
            int k = connReceive.Receive(resultByte);
            connReceive.Close();
            OutputLineTab2("收到SERVER发送的数据" + k.ToString());
            OutputLineTab2(BitConverter.ToString(resultByte.Take(k).ToArray()));
        }

        private void BtnSendContent_Click(object sender, EventArgs e)
        {
            Socket socketSend = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            if (socketSend != null && socketSend.Connected)
            {
                byte[] rr = Encoding.UTF8.GetBytes("010400000020F1D2");

                int i = socketSend.Send(rr, SocketFlags.None);
                //
                OutputLineTab2("已发送成功");
                //
                byte[] resultByte = new byte[1024];
                int k = socketSend.Receive(resultByte);
                OutputLineTab2("收到SERVER发送的数据" + k.ToString());
                //socketSend.Close();
            }
        }

        private void BtnClearTabPage3_Click(object sender, EventArgs e)
        {
            textBox1.Clear();
        }

        private DataTable initCommand()
        {
            DataTable dataTable = new DataTable();
            dataTable.Columns.Add("keyName");
            dataTable.Columns.Add("Value");

            dataTable.Rows.Add("打开第1路继电器", "01 05 00 00 FF 00 8C 3A");
            dataTable.Rows.Add("关闭第1路继电器", "01 05 00 00 00 00 CD CA");

            dataTable.Rows.Add("打开第2路继电器", "01 05 00 01 FF 00 DD FA");
            dataTable.Rows.Add("关闭第2路继电器", "01 05 00 01 00 00 9C 0A");

            dataTable.Rows.Add("打开第3路继电器", "01 05 00 02 FF 00 2D FA");
            dataTable.Rows.Add("关闭第3路继电器", "01 05 00 02 00 00 6C 0A");

            dataTable.Rows.Add("打开第4路继电器", "01 05 00 03 FF 00 7C 3A");
            dataTable.Rows.Add("关闭第4路继电器", "01 05 00 03 00 00 3D CA");

            dataTable.Rows.Add("关闭所有继电器", "01 0F 00 00 00 20 04 00 00 00 00 C4 88");
            dataTable.Rows.Add("打开所有继电器", "01 0F 00 00 00 20 04 FF FF FF FF C5 1C");

            dataTable.AcceptChanges();

            return dataTable;
        }

        private void BindCombobox()
        {
            DataTable dataTable = initCommand();
            comboBox1.DataSource = dataTable;
            comboBox1.DisplayMember = dataTable.Columns[0].ColumnName;
            comboBox1.ValueMember = dataTable.Columns[1].ColumnName;
            comboBox1.DropDownStyle = ComboBoxStyle.DropDownList;

            comboBox1.SelectedIndexChanged -= ComboBox1_SelectedIndexChanged;
            comboBox1.SelectedIndexChanged += ComboBox1_SelectedIndexChanged;
        }

        private void ComboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            ComboBox cbx = sender as ComboBox;
            DataRowView dataRow = cbx.SelectedItem as DataRowView;
            txtSend.Text = dataRow[1].ToString();
        }

        #region TabPage5

        private void BtnOpenForth_Click(object sender, EventArgs e)
        {
            string openCommand = "01 05 00 03 FF 00 7C 3A";
            OpenClose(openCommand);
        }

        private void OpenClose(string command)
        {
            Socket socketSend = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            int port = Convert.ToInt32(nudPort3.Value);

            socketSend.BeginConnect(txtIPAddr3.Text.Trim(), port, new AsyncCallback((iasyncResult) =>
            {
                try
                {
                    Socket socket = iasyncResult.AsyncState as Socket;
                    socket.EndConnect(iasyncResult);
                    OutputTxt3("连接成功");
                    //string openCommand = "01 05 00 03 FF 00 7C 3A";
                    //string closeCommand = "01 05 00 03 00 00 3D CA";
                    socket.Send(CRC.StringToHexByte(command.Replace(" ", "")));
                    OutputTxt3("发送成功:" + command);
                    byte[] temp = new byte[1024];
                    int k = socket.Receive(temp, temp.Length, SocketFlags.None);
                    OutputTxt3("收到数据：" + CRC.ByteToString(temp.Take(k).ToArray()));
                    //
                    socket.Close();
                    OutputTxt3("连接关闭");
                }
                catch (Exception exc)
                {
                    OutputTxt3(exc.Message);
                }
            }), socketSend);
        }

        private void BtnCloseForth_Click(object sender, EventArgs e)
        {
            string closeCommand = "01 05 00 03 00 00 3D CA";
            OpenClose(closeCommand);
        }

        private void OutputTxt3(string txt)
        {
            txtLog3.BeginInvoke(new MethodInvoker(() =>
            {
                txtLog3.AppendText(txt);
                txtLog3.AppendText(Environment.NewLine);
            }));
        }

        System.Threading.Timer timerLong = null;
        System.Threading.Timer timerShort = null;
        int openNums = 60;

        private void BtnAutoRun_Click(object sender, EventArgs e)
        {
            int intervalLong = ((int)nudIntervalLong.Value) * 1000;
            int stopInterval = ((int)nudStopInterval.Value) * 1000;
            int intervalShortInLong = ((int)nudIntervalInLong.Value) * 1000;

            SetFlag(true);
            timerLong = new System.Threading.Timer(new System.Threading.TimerCallback((obj) =>
            {
                bool x = GetFlag();
                if (x)
                {
                    openNums = intervalLong;
                    timerShort.Change(0, intervalShortInLong);
                }
                else
                {
                    //停止周期内计时器
                    timerShort.Change(System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite);
                    //
                    timerLong.Change(stopInterval, intervalLong);
                    //
                    string closeCommand = "01 05 00 03 00 00 3D CA";
                    OpenClose(closeCommand);
                }
                SetFlag(!x);
            }), null, 0, intervalLong);

            SetFlag2(true);
            timerShort = new System.Threading.Timer(new System.Threading.TimerCallback((obj) =>
            {
                if (openNums <= 0)
                {
                    //长周期消耗完了，停止短计时器
                    timerShort.Change(System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite);
                }
                else
                {
                    bool y = GetFlag2();
                    if (y)
                    {
                        //每振停一次，就将时间减一
                        openNums = openNums - intervalShortInLong;
                        string openCommand = "01 05 00 03 FF 00 7C 3A";
                        OpenClose(openCommand);
                    }
                    else
                    {
                        string closeCommand = "01 05 00 03 00 00 3D CA";
                        OpenClose(closeCommand);
                    }
                    SetFlag2(!y);
                }
            }), null, 0, intervalShortInLong);

        }

        private delegate bool FlagGetHandle();
        private delegate void FlagSetHandle(bool torf);

        private bool GetFlag()
        {
            object obj = btnAutoRun.Invoke(new FlagGetHandle(() =>
            {
                if (btnAutoRun.Tag == null)
                    return false;
                else if (btnAutoRun.Tag is bool)
                {
                    return (bool)btnAutoRun.Tag;
                }
                return false;
            }));
            return (bool)obj;
        }

        private void SetFlag(bool torf)
        {
            btnAutoRun.Invoke(new FlagSetHandle((torf2) =>
            {
                btnAutoRun.Tag = torf2;
            }), torf);
        }

        private bool GetFlag2()
        {
            object obj = txtIPAddr3.Invoke(new FlagGetHandle(() =>
            {
                if (txtIPAddr3.Tag == null)
                    return false;
                else if (txtIPAddr3.Tag is bool)
                {
                    return (bool)txtIPAddr3.Tag;
                }
                return false;
            }));
            return (bool)obj;
        }

        private void SetFlag2(bool torf)
        {
            txtIPAddr3.Invoke(new FlagSetHandle((torf2) =>
            {
                txtIPAddr3.Tag = torf2;
            }), torf);
        }

        private void Button1_Click(object sender, EventArgs e)
        {
            timerLong.Change(System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite);
            timerShort.Change(System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite);
        }

        #endregion

        #region TabPage6-深南烤箱温控器
        List<GroupBox> listSelect = new List<GroupBox>();
        private void initTabPage3()
        {
            foreach (object item in cmbRuleMode.Items)
            {
                var r = item.ToString().Split('.');
                string name = "groupBox" + r[0];
                var y = tabPage6.Controls.Find(name, false);
                if (y.Length > 0)
                {
                    listSelect.Add(y[0] as GroupBox);
                }
                else
                {
                    listSelect.Add(null);
                }
            }

            cmbRuleMode.SelectedIndex = 0;
        }

        frmSetComPort setComPort = new frmSetComPort();

        private void btn3SetComm_Click(object sender, EventArgs e)
        {
            if (setComPort.ShowDialog() != DialogResult.OK)
            {
                return;
            }
            txt3ComPort.Text = setComPort.PortName;
            txt3BaudRate.Text = setComPort.BaudRate.ToString();
            txt3DataBits.Text = setComPort.DataBits.ToString();
            txt3StopBits.Text = setComPort.StopBits.ToString();
            txt3Parity.Text = setComPort.Parity.ToString();
            //
            serialPort6.PortName = setComPort.PortName;
            serialPort6.BaudRate = setComPort.BaudRate;
            serialPort6.DataBits = setComPort.DataBits;
            serialPort6.StopBits = setComPort.StopBits;
            serialPort6.Parity = setComPort.Parity;
        }

        private void SP3State(bool open)
        {
            btn3Open.Enabled = !open;
            btn3close.Enabled = open;
            btn3SetComm.Enabled = !open;
        }

        private void btn3Open_Click(object sender, EventArgs e)
        {
            serialPort6.DataReceived += SerialPort6_DataReceived;
            serialPort6.Open();
            SP3State(serialPort6.IsOpen);
        }

        Func<int> handlerSleepTime = null;
        private int GetSleepTime()
        {
            if (handlerSleepTime == null)
            {
                handlerSleepTime = new Func<int>(() =>
                {
                    int t;
                    if (!int.TryParse(txt3SleepTime.Text.Trim(), out t))
                    {
                        t = 0;
                    }
                    return t;
                });
            }
            object obj = txt3SleepTime.Invoke(handlerSleepTime);
            return Convert.ToInt32(obj);
        }

        private void SerialPort6_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            SerialPort sp = sender as SerialPort;
            int sleeptime = GetSleepTime();
            System.Threading.Thread.Sleep(sleeptime);
            int length = sp.BytesToRead;
            //
            byte[] data = new byte[length];
            sp.Read(data, 0, length);
            Output3("收到数据 " + BitConverter.ToString(data));
            //
            byte[] r = DealData(data);
            if (r.Length > 0)
            {
                sp.Write(r, 0, r.Length);
                Output3Line("返回数据 " + BitConverter.ToString(r));
            }
            else
            {
                Output3Line(" -- 处理结束");
            }
        }

        Func<byte[], byte[]> HandlerDealData = null;

        private byte[] DealData(byte[] data)
        {
            if (HandlerDealData == null)
            {
                HandlerDealData = new Func<byte[], byte[]>((bytes) =>
                {
                    byte[] result = new byte[0];
                    if (bytes.Length == 0)
                        return result;
                    //
                    int r = GetRule();
                    Output3($" --当前规则是{r}");
                    //
                    byte[] temp = new byte[0];
                    switch (r)
                    {
                        case 1:
                            //温度传感器
                            temp = new byte[] { 0x01, 0x03, 0x00, 0xC0, 0x00, 0x04, 0x44, 0x35 };
                            if (bytes[1] == 0x03 && bytes[2] == 0x00 && bytes[3] == 0xC0 && bytes[4] == 0x00 && bytes[5] == 0x04)
                            {
                                byte[] rdata = new byte[11] { bytes[0], bytes[1], 0x08, 0x00, 0x19, 0x00, 0x14, 0x00, 0x00, 0x00, 0x40 };
                                //超温标记
                                bool overtemp = GetOverTemperature();
                                rdata[8] = (byte)(overtemp ? 0x01 : 0x00);
                                //温控器运行或停止
                                bool running = GetRunning();
                                rdata[10] = (byte)(running ? 0x10 : 0x40);
                                result = new byte[13];
                                Array.Copy(rdata, result, rdata.Length);
                                byte[] crc = CRC.CRC16(rdata, true);
                                Array.Copy(crc, 0, result, rdata.Length, crc.Length);
                            }
                            else if (bytes[1] == 0x06)
                            {
                                result = new byte[bytes.Length];
                                Array.Copy(bytes, result, bytes.Length);
                            }
                            else
                            {
                                Output3Line("收到数据不符合所选规则");
                            }
                            break;
                        case 2:
                            //E820输入通道1和2
                            if (bytes[1] == 0x03 && bytes[2] == 0x00 && new byte[] { 0x11, 0x12, 0x41, 0x42 }.Contains(bytes[3]))
                            {
                                //读取AI1、AI2、AO1、AO2的值
                                byte len = (byte)(bytes[5] * 2);
                                byte[] xxd = new byte[len];
                                int f1 = GetNUDValue(tab3Rule2AI1From);
                                int t1 = GetNUDValue(tab3Rule2AI1To);
                                short x = (short)random.Next(f1, t1);
                                byte[] a1 = BitConverter.GetBytes(x);
                                temp = new byte[3 + len];
                                result = new byte[5 + len];
                                temp[0] = bytes[0];
                                temp[1] = bytes[1];
                                temp[2] = len;
                                Array.Copy(a1, 0, temp, 3, a1.Length);
                                if (len == 4)
                                {
                                    int f2 = GetNUDValue(tab3Rule2AI2From);
                                    int t2 = GetNUDValue(tab3Rule2AI2To);
                                    short y = (short)random.Next(f2, t2);
                                    byte[] a2 = BitConverter.GetBytes(y);
                                    Array.Copy(a2, 0, temp, 5, a2.Length);
                                }
                                byte[] crc2 = CRC.CRC16(temp, true);
                                Array.Copy(temp, result, temp.Length);
                                Array.Copy(crc2, 0, result, temp.Length, crc2.Length);

                            }
                            else
                            {
                                Output3Line("收到数据不符合所选规则");
                            }
                            break;
                        case 3:
                            //0x01, 0x05, 0x00, 0x00, 0xFF, 0x00, 0x8C, 0x3A
                            //0x01, 0x05, 0x00, 0x00, 0x00, 0x00, 0xCD, 0xCA
                            if (bytes[0] == 0x01 && bytes[1] == 0x05 && bytes[2] == 0x00 && bytes[3] == 0x00
                                && bytes[4] == 0xFF && bytes[5] == 0x00 && bytes[6] == 0x8C && bytes[7] == 0x3A)
                            {
                                OpenAlert();
                            }
                            else if (bytes[0] == 0x01 && bytes[1] == 0x05 && bytes[2] == 0x00 && bytes[3] == 0x00
                              && bytes[4] == 0x00 && bytes[5] == 0x00 && bytes[6] == 0xCD && bytes[7] == 0xCA)
                            {
                                CloseAlert();
                            }
                            break;
                        case 4:
                            //enq-0-F-F-F 
                            if (bytes[0] == 0x05 && bytes[1] == 0x30 && bytes[2] == 0x46 && bytes[3] == 0x46 && bytes[4] == 0x46 
                                && bytes[8] == 0x58 && bytes[9] == 0x30 && bytes[10] == 0x30 && bytes[11] == 0x30 && bytes[12] == 0x30
                            )
                            {
                                if (bytes[5] == 0x57 && bytes[6] == 0x52)
                                {
                                    //WR
                                }
                                else if (bytes[5] == 0x57 && bytes[6] == 0x52)
                                {
                                    //BR

                                }
                            }
                            break;
                        case 5:
                            //01 03 00 0C 00 04 84 0A
                            //E820输入通道1和2
                            if (bytes[1] == 0x03 && bytes[2] == 0x00 && bytes[3] == 0x0C && bytes[4] == 0x00 && bytes[5] == 0x04)
                            {
                                byte len = (byte)(bytes[5] * 2);
                                temp = new byte[3 + len];
                                result = new byte[5 + len];
                                //
                                temp[0] = bytes[0];
                                temp[1] = bytes[1];
                                temp[2] = len;
                                //
                                int f1 = GetNUDValue(tab3Rule5AI1From);
                                int t1 = GetNUDValue(tab3Rule5AI1To);
                                short x1 = (short)random.Next(f1, t1);
                                byte[] a1 = BitConverter.GetBytes(x1);
                                Array.Copy(a1, 0, temp, 3, a1.Length);
                                //
                                int f2 = GetNUDValue(tab3Rule5AI2From);
                                int t2 = GetNUDValue(tab3Rule5AI2To);
                                short x2 = (short)random.Next(f2, t2);
                                byte[] a2 = BitConverter.GetBytes(x2);
                                Array.Copy(a2, 0, temp, 5, a2.Length);
                                //
                                int f3 = GetNUDValue(tab3Rule5AI3From);
                                int t3 = GetNUDValue(tab3Rule5AI3To);
                                short x3 = (short)random.Next(f3, t3);
                                byte[] a3 = BitConverter.GetBytes(x3);
                                Array.Copy(a3, 0, temp, 7, a3.Length);
                                //
                                int f4 = GetNUDValue(tab3Rule5AI4From);
                                int t4 = GetNUDValue(tab3Rule5AI4To);
                                short x4 = (short)random.Next(f2, t2);
                                byte[] a4 = BitConverter.GetBytes(x4);
                                Array.Copy(a4, 0, temp, 9, a4.Length);
                                //
                                byte[] crc2 = CRC.CRC16(temp, true);
                                Array.Copy(temp, result, temp.Length);
                                Array.Copy(crc2, 0, result, temp.Length, crc2.Length);
                            }
                            else
                            {
                                Output3Line("收到数据不符合所选规则");
                            }
                            break;
                        default:
                            break;
                    }
                    return result;
                });
            }
            byte[] rr = HandlerDealData.Invoke(data);
            return rr;
        }

        private void btn3close_Click(object sender, EventArgs e)
        {
            serialPort6.DataReceived -= SerialPort6_DataReceived;
            serialPort6.Close();
            SP3State(serialPort6.IsOpen);
        }

        #region 从界面取值

        Func<int> handlerRule = null;

        private int GetRule()
        {
            if (handlerRule == null)
            {
                handlerRule = new Func<int>(() =>
                {
                    if (cmbRuleMode.SelectedIndex == -1)
                    {
                        return -1;
                    }
                    else
                    {
                        var s = cmbRuleMode.SelectedItem.ToString();
                        var i = s.IndexOf('.');
                        var o = s.Substring(0, i);
                        return Convert.ToInt32(o);
                    }
                });
            }

            var xx = cmbRuleMode.Invoke(handlerRule);
            return Convert.ToInt32(xx);
        }

        Func<CheckBox, bool> handlerGetCheckBoxValue = null;

        private bool GetRunning()
        {
            if (handlerGetCheckBoxValue == null)
            {
                handlerGetCheckBoxValue = new Func<CheckBox, bool>((cbx) =>
                {
                    return cbx.Checked;
                });
            }
            object ob = cbxRunning.Invoke(handlerGetCheckBoxValue, cbxRunning);
            return (bool)ob;
        }

        private bool GetOverTemperature()
        {
            if (handlerGetCheckBoxValue == null)
            {
                handlerGetCheckBoxValue = new Func<CheckBox, bool>((cbx) =>
                {
                    return cbx.Checked;
                });
            }
            object ob = cbxOverTemperature.Invoke(handlerGetCheckBoxValue, cbxOverTemperature);
            return (bool)ob;
        }

        Func<NumericUpDown, decimal> handlerNumericUpDown = null; 
        private int GetNUDValue(NumericUpDown nud)
        {
            if (handlerNumericUpDown == null)
            {
                handlerNumericUpDown = new Func<NumericUpDown, decimal>((xnud) => {
                    return xnud.Value;
                });
            }
            object obj = this.Invoke(handlerNumericUpDown, nud);
            return Convert.ToInt32(obj);
        }

        #endregion

        MethodInvoker miOpenAlert = null, miCloseAlert = null;
        private void OpenAlert()
        {
            if (miOpenAlert == null)
            {
                miOpenAlert = new MethodInvoker(() =>
                {
                    pictureBox1.Image = imageList1.Images[1];
                });
            }
            this.Invoke(miOpenAlert);
        }
        private void CloseAlert()
        {
            if (miCloseAlert == null)
            {
                miCloseAlert = new MethodInvoker(() =>
                {
                    pictureBox1.Image = imageList1.Images[0];
                });
            }
            this.Invoke(miCloseAlert);
        }

        private void cmbRuleMode_SelectedIndexChanged(object sender, EventArgs e)
        {
            ComboBox box = sender as ComboBox;
            if (box.SelectedIndex == -1) { return; }
            tabControl3.SelectedIndex = box.SelectedIndex;
            //for (int i = 0; i < box.Items.Count; i++)
            //{
            //    GroupBox gb = listSelect[i] as GroupBox;
            //    if (gb != null)
            //    {
            //        gb.Visible = (i == box.SelectedIndex);
            //        gb.Left = txt3SleepTime.Left;
            //    }
            //}
        }

        #region text.output

        Action<string> handler3Output = null;

        private void Output3(string msg)
        {
            if (handler3Output == null)
            {
                handler3Output = new Action<string>((txt) =>
                {
                    txt3Log.AppendText(txt);
                });
            }
            txt3Log.BeginInvoke(handler3Output, msg);
        }

        private void Output3Line(string msg)
        {
            Output3(msg + Environment.NewLine);
        }

        #endregion

        private void btnClear_Click(object sender, EventArgs e)
        {
            txt3Log.Clear();
        }

        #endregion
    }
}